Interactive map of traffic accidents in the metropolitan region of São Paulo, clustered by region and type, during the year 2015.
Appendix I - Source Code
Made with R and Leaflet, source code:
# load libraries
# install.packages("leaflet")
# install.packages("dplyr")
suppressPackageStartupMessages(library(leaflet))
suppressPackageStartupMessages(library(stringr))
suppressPackageStartupMessages(library(dplyr))
#load and clean
data2015 <- read.csv("./dados/2015/ocorrencias-transito-pmsp-2015.csv")
data2015$lng <- as.numeric(str_match(data2015$WKT, ".*\\((.*)\\s(.*)\\)")[,2])
data2015$lat <- as.numeric(str_match(data2015$WKT, ".*\\((.*)\\s(.*)\\)")[,3])
data2015 <- data2015[complete.cases(data2015[,c("lat","lng")]),]
# add legenda com o TIPO_ACIDE
data2015$TIPO_ACIDE_DESCR[data2015$TIPO_ACIDE=="CO"] <- "Colisão"
data2015$TIPO_ACIDE_DESCR[data2015$TIPO_ACIDE=="CF"] <- "Colisão frontal"
data2015$TIPO_ACIDE_DESCR[data2015$TIPO_ACIDE=="CT"] <- "Colisão traseira"
data2015$TIPO_ACIDE_DESCR[data2015$TIPO_ACIDE=="CL"] <- "Colisão lateral"
data2015$TIPO_ACIDE_DESCR[data2015$TIPO_ACIDE=="CV"] <- "Colisão Transversa"
data2015$TIPO_ACIDE_DESCR[data2015$TIPO_ACIDE=="CP"] <- "Capotamento"
data2015$TIPO_ACIDE_DESCR[data2015$TIPO_ACIDE=="TB"] <- "Tombamento"
data2015$TIPO_ACIDE_DESCR[data2015$TIPO_ACIDE=="AT"] <- "Atropelamento"
data2015$TIPO_ACIDE_DESCR[data2015$TIPO_ACIDE=="AA"] <- "Atropelamento animal"
data2015$TIPO_ACIDE_DESCR[data2015$TIPO_ACIDE=="CH"] <- "Choque"
data2015$TIPO_ACIDE_DESCR[data2015$TIPO_ACIDE=="QM"] <- "Queda moto/bicicleta"
data2015$TIPO_ACIDE_DESCR[data2015$TIPO_ACIDE=="QV"] <- "Queda veículo"
data2015$TIPO_ACIDE_DESCR[data2015$TIPO_ACIDE=="QD"] <- "Queda ocupante dentro"
data2015$TIPO_ACIDE_DESCR[data2015$TIPO_ACIDE=="QF"] <- "Queda ocupante fora"
data2015$TIPO_ACIDE_DESCR[data2015$TIPO_ACIDE=="OU"] <- "Outros"
data2015$TIPO_ACIDE_DESCR[data2015$TIPO_ACIDE=="SI"] <- "Sem informação"
# normaliza numero de vitimas
data2015$VITIMAS_NORM[data2015$VITIMAS < 100] <- data2015[data2015$VITIMAS < 100,17]
data2015$VITIMAS_NORM[data2015$VITIMAS >= 100] <- data2015[data2015$VITIMAS >= 100,17] %/% 100
data2015$VITIMAS_MORTE <- 0
data2015$VITIMAS_MORTE[data2015$VITIMAS >= 100] <- data2015[data2015$VITIMAS >= 100,17] %% 100
# popup
data2015$popup <- paste(data2015$TIPO_ACIDE_DESCR, "<br><br>vitimas feridas:", data2015$VITIMAS_NORM, "<br>vitimas fatais:", data2015$VITIMAS_MORTE, "<br>cod. localização: ", data2015$CADLOGA);
# color
data2015$color[data2015$COD_ACID==2] <- "blue"
data2015$color[data2015$COD_ACID==4] <- "red"
# top 10 locations
locations <- data2015 %>%
group_by(WKT) %>%
summarize(n=n(), vitimas=sum(VITIMAS_NORM), vitimas_morte=sum(VITIMAS_MORTE))
locations$lng <- as.numeric(str_match(locations$WKT, ".*\\((.*)\\s(.*)\\)")[,2])
locations$lat <- as.numeric(str_match(locations$WKT, ".*\\((.*)\\s(.*)\\)")[,3])
locations <- arrange(locations, desc(n))
top10 <- head(locations, 10)
top10$popup <- paste("<b>TOP 10 in number of accidents</b><br><br>total accidents: ", top10$n, "<br>victims: ", top10$vitimas, "<br>deaths: ", top10$vitimas_morte)
locations <- arrange(locations, desc(vitimas_morte))
deadly <- head(locations, 10)
deadly$popup <- paste("<b>Deadly Location</b><br><br>total accidents: ", deadly$n, "<br>victims: ", deadly$vitimas, "<br>deaths: ", deadly$vitimas_morte)
# most run over
run_over <- data2015[data2015$COD_ACID==4,] %>%
group_by(WKT) %>%
summarize(n=n(), vitimas=sum(VITIMAS_NORM), vitimas_morte=sum(VITIMAS_MORTE))
run_over$lng <- as.numeric(str_match(run_over$WKT, ".*\\((.*)\\s(.*)\\)")[,2])
run_over$lat <- as.numeric(str_match(run_over$WKT, ".*\\((.*)\\s(.*)\\)")[,3])
run_over <- arrange(run_over, desc(n))
run_over <- head(run_over, 5)
run_over$popup <- paste("<b>Top 5 in run over</b><br><br>total accidents: ", run_over$n, "<br>victims: ", run_over$vitimas, "<br>deaths: ", run_over$vitimas_morte)
# cruza dados dos logradouros
logradouros <- read.csv("./dados/logradouros.csv")
# levels(logradouros$classificacao)
logradouros <- logradouros %>%
filter(classificacao == "Transito Rápido", codlog5 != "NULL") %>%
group_by(codlog5) %>%
summarize(n=n())
run_over_rapido <- data2015 %>%
filter(COD_ACID==4, CADLOGA %in% logradouros$codlog5)
# factpal <- colorFactor(topo.colors(17), data2015$TIPO_ACIDE, alpha = FALSE, ordered = TRUE)
data2015 %>% leaflet(width=800, height=500, padding=5) %>% addTiles() %>%
addCircleMarkers(data = data2015, popup=~popup, clusterOptions = markerClusterOptions(), group="all accidents", color=~color, radius = ~VITIMAS_NORM * 4, weight = 3, fillOpacity = ~VITIMAS_MORTE + 0.2 ) %>%
addCircleMarkers(data = run_over_rapido, popup=~popup, group="atropelamentos nas vias expressas", color=~color, radius = 8, weight = 3, fillOpacity = ~VITIMAS_MORTE + 0.2 ) %>%
addCircleMarkers(data = data2015[data2015$COD_ACID==4,], popup=~popup, clusterOptions = markerClusterOptions(), group="somente atropelamentos", color=~color, radius = ~VITIMAS_NORM * 4, weight = 3, fillOpacity = ~VITIMAS_MORTE + 0.2 ) %>%
addMarkers(data=top10, group="worst location", popup=~popup)%>%
addMarkers(data=deadly, group="deadly", popup=~popup)%>%
addMarkers(data=run_over, group="somente atropelamentos", popup=~popup)%>%
addLayersControl(
baseGroups = c("all accidents", "somente atropelamentos", "atropelamentos nas vias expressas"),
overlayGroups = c("worst location", "deadly"),
options = layersControlOptions(collapsed = FALSE),
position="bottomleft"
)
LS0tCnRpdGxlOiAiVHJhZmZpYyBBY2NpZGVudHMgaW4gdGhlIE1ldHJvcG9saXRhbiBSZWdpb24gb2YgU8OjbyBQYXVsbyAtIDIwMTUiCmF1dGhvcjogIldhZ25lciBQaW5oZWlybyIKZGF0ZTogIkphbnVhcnksIDIwMTciCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IHVuaXRlZAogIGh0bWxfbm90ZWJvb2s6CiAgICBmaWdfd2lkdGg6IDE2CiAgICB0aGVtZTogdW5pdGVkCi0tLQoKCkludGVyYWN0aXZlIG1hcCBvZiB0cmFmZmljIGFjY2lkZW50cyBpbiB0aGUgbWV0cm9wb2xpdGFuIHJlZ2lvbiBvZiBTw6NvIFBhdWxvLCBjbHVzdGVyZWQgYnkgcmVnaW9uIGFuZCB0eXBlLCBkdXJpbmcgdGhlIHllYXIgMjAxNS4KClRoYW5rcyB0byB0aGUgcHJvamVjdCBbQ8OzZGlnbyBVcmJhbm9dKGh0dHBzOi8vZ2l0aHViLmNvbS9jb2RpZ291cmJhbm8pIGZvciBtYWtpbmcgcHVibGljIGFjY2VzcyB0byB0aGlzIGRhdGEuCgoKYGBge3IsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMgbG9hZCBsaWJyYXJpZXMKIyBpbnN0YWxsLnBhY2thZ2VzKCJsZWFmbGV0IikKIyBpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpCnN1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyhsaWJyYXJ5KGxlYWZsZXQpKQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMobGlicmFyeShzdHJpbmdyKSkKc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKGxpYnJhcnkoZHBseXIpKQoKI2xvYWQgYW5kIGNsZWFuCmRhdGEyMDE1IDwtIHJlYWQuY3N2KCIuL2RhZG9zLzIwMTUvb2NvcnJlbmNpYXMtdHJhbnNpdG8tcG1zcC0yMDE1LmNzdiIpCmRhdGEyMDE1JGxuZyA8LSBhcy5udW1lcmljKHN0cl9tYXRjaChkYXRhMjAxNSRXS1QsICIuKlxcKCguKilcXHMoLiopXFwpIilbLDJdKQpkYXRhMjAxNSRsYXQgPC0gYXMubnVtZXJpYyhzdHJfbWF0Y2goZGF0YTIwMTUkV0tULCAiLipcXCgoLiopXFxzKC4qKVxcKSIpWywzXSkKZGF0YTIwMTUgPC0gZGF0YTIwMTVbY29tcGxldGUuY2FzZXMoZGF0YTIwMTVbLGMoImxhdCIsImxuZyIpXSksXQoKIyBhZGQgbGVnZW5kYSBjb20gbyBUSVBPX0FDSURFCmRhdGEyMDE1JFRJUE9fQUNJREVfREVTQ1JbZGF0YTIwMTUkVElQT19BQ0lERT09IkNPIl0gPC0gIkNvbGlzw6NvIgpkYXRhMjAxNSRUSVBPX0FDSURFX0RFU0NSW2RhdGEyMDE1JFRJUE9fQUNJREU9PSJDRiJdIDwtICJDb2xpc8OjbyBmcm9udGFsIgpkYXRhMjAxNSRUSVBPX0FDSURFX0RFU0NSW2RhdGEyMDE1JFRJUE9fQUNJREU9PSJDVCJdIDwtICJDb2xpc8OjbyB0cmFzZWlyYSIKZGF0YTIwMTUkVElQT19BQ0lERV9ERVNDUltkYXRhMjAxNSRUSVBPX0FDSURFPT0iQ0wiXSA8LSAiQ29saXPDo28gbGF0ZXJhbCIKZGF0YTIwMTUkVElQT19BQ0lERV9ERVNDUltkYXRhMjAxNSRUSVBPX0FDSURFPT0iQ1YiXSA8LSAiQ29saXPDo28gVHJhbnN2ZXJzYSIKZGF0YTIwMTUkVElQT19BQ0lERV9ERVNDUltkYXRhMjAxNSRUSVBPX0FDSURFPT0iQ1AiXSA8LSAiQ2Fwb3RhbWVudG8iCmRhdGEyMDE1JFRJUE9fQUNJREVfREVTQ1JbZGF0YTIwMTUkVElQT19BQ0lERT09IlRCIl0gPC0gIlRvbWJhbWVudG8iCmRhdGEyMDE1JFRJUE9fQUNJREVfREVTQ1JbZGF0YTIwMTUkVElQT19BQ0lERT09IkFUIl0gPC0gIkF0cm9wZWxhbWVudG8iCmRhdGEyMDE1JFRJUE9fQUNJREVfREVTQ1JbZGF0YTIwMTUkVElQT19BQ0lERT09IkFBIl0gPC0gIkF0cm9wZWxhbWVudG8gYW5pbWFsIgpkYXRhMjAxNSRUSVBPX0FDSURFX0RFU0NSW2RhdGEyMDE1JFRJUE9fQUNJREU9PSJDSCJdIDwtICJDaG9xdWUiCmRhdGEyMDE1JFRJUE9fQUNJREVfREVTQ1JbZGF0YTIwMTUkVElQT19BQ0lERT09IlFNIl0gPC0gIlF1ZWRhIG1vdG8vYmljaWNsZXRhIgpkYXRhMjAxNSRUSVBPX0FDSURFX0RFU0NSW2RhdGEyMDE1JFRJUE9fQUNJREU9PSJRViJdIDwtICJRdWVkYSB2ZcOtY3VsbyIKZGF0YTIwMTUkVElQT19BQ0lERV9ERVNDUltkYXRhMjAxNSRUSVBPX0FDSURFPT0iUUQiXSA8LSAiUXVlZGEgb2N1cGFudGUgZGVudHJvIgpkYXRhMjAxNSRUSVBPX0FDSURFX0RFU0NSW2RhdGEyMDE1JFRJUE9fQUNJREU9PSJRRiJdIDwtICJRdWVkYSBvY3VwYW50ZSBmb3JhIgpkYXRhMjAxNSRUSVBPX0FDSURFX0RFU0NSW2RhdGEyMDE1JFRJUE9fQUNJREU9PSJPVSJdIDwtICJPdXRyb3MiCmRhdGEyMDE1JFRJUE9fQUNJREVfREVTQ1JbZGF0YTIwMTUkVElQT19BQ0lERT09IlNJIl0gPC0gIlNlbSBpbmZvcm1hw6fDo28iCgojIG5vcm1hbGl6YSBudW1lcm8gZGUgdml0aW1hcwpkYXRhMjAxNSRWSVRJTUFTX05PUk1bZGF0YTIwMTUkVklUSU1BUyA8IDEwMF0gPC0gZGF0YTIwMTVbZGF0YTIwMTUkVklUSU1BUyA8IDEwMCwxN10KZGF0YTIwMTUkVklUSU1BU19OT1JNW2RhdGEyMDE1JFZJVElNQVMgPj0gMTAwXSA8LSBkYXRhMjAxNVtkYXRhMjAxNSRWSVRJTUFTID49IDEwMCwxN10gJS8lIDEwMApkYXRhMjAxNSRWSVRJTUFTX01PUlRFIDwtIDAKZGF0YTIwMTUkVklUSU1BU19NT1JURVtkYXRhMjAxNSRWSVRJTUFTID49IDEwMF0gPC0gZGF0YTIwMTVbZGF0YTIwMTUkVklUSU1BUyA+PSAxMDAsMTddICUlIDEwMAoKIyBwb3B1cApkYXRhMjAxNSRwb3B1cCA8LSBwYXN0ZShkYXRhMjAxNSRUSVBPX0FDSURFX0RFU0NSLCAiPGJyPjxicj52aXRpbWFzIGZlcmlkYXM6IiwgZGF0YTIwMTUkVklUSU1BU19OT1JNLCAiPGJyPnZpdGltYXMgZmF0YWlzOiIsIGRhdGEyMDE1JFZJVElNQVNfTU9SVEUsICI8YnI+Y29kLiBsb2NhbGl6YcOnw6NvOiAiLCBkYXRhMjAxNSRDQURMT0dBKTsKCiMgY29sb3IKZGF0YTIwMTUkY29sb3JbZGF0YTIwMTUkQ09EX0FDSUQ9PTJdIDwtICJibHVlIgpkYXRhMjAxNSRjb2xvcltkYXRhMjAxNSRDT0RfQUNJRD09NF0gPC0gInJlZCIgCgojIHRvcCAxMCBsb2NhdGlvbnMKbG9jYXRpb25zIDwtIGRhdGEyMDE1ICU+JQogIGdyb3VwX2J5KFdLVCkgJT4lCiAgc3VtbWFyaXplKG49bigpLCB2aXRpbWFzPXN1bShWSVRJTUFTX05PUk0pLCB2aXRpbWFzX21vcnRlPXN1bShWSVRJTUFTX01PUlRFKSkKCmxvY2F0aW9ucyRsbmcgPC0gYXMubnVtZXJpYyhzdHJfbWF0Y2gobG9jYXRpb25zJFdLVCwgIi4qXFwoKC4qKVxccyguKilcXCkiKVssMl0pCmxvY2F0aW9ucyRsYXQgPC0gYXMubnVtZXJpYyhzdHJfbWF0Y2gobG9jYXRpb25zJFdLVCwgIi4qXFwoKC4qKVxccyguKilcXCkiKVssM10pCiMgbG9jYXRpb25zJGxuZzEgPC0gbG9jYXRpb25zJGxuZyAtIDAuMDAxCiMgbG9jYXRpb25zJGxhdDEgPC0gbG9jYXRpb25zJGxhdCAtIDAuMDAxCiMgbG9jYXRpb25zJGxuZzIgPC0gbG9jYXRpb25zJGxuZyArIDAuMDAxCiMgbG9jYXRpb25zJGxhdDIgPC0gbG9jYXRpb25zJGxhdCArIDAuMDAxCgpsb2NhdGlvbnMgPC0gYXJyYW5nZShsb2NhdGlvbnMsIGRlc2MobikpCgp0b3AxMCA8LSBoZWFkKGxvY2F0aW9ucywgMTApCgp0b3AxMCRwb3B1cCA8LSBwYXN0ZSgiPGI+VE9QIDEwIGluIG51bWJlciBvZiBhY2NpZGVudHM8L2I+PGJyPjxicj50b3RhbCBhY2NpZGVudHM6ICIsIHRvcDEwJG4sICI8YnI+dmljdGltczogIiwgdG9wMTAkdml0aW1hcywgIjxicj5kZWF0aHM6ICIsIHRvcDEwJHZpdGltYXNfbW9ydGUpCgpsb2NhdGlvbnMgPC0gYXJyYW5nZShsb2NhdGlvbnMsIGRlc2Modml0aW1hc19tb3J0ZSkpCmRlYWRseSA8LSBoZWFkKGxvY2F0aW9ucywgMTApCmRlYWRseSRwb3B1cCA8LSBwYXN0ZSgiPGI+RGVhZGx5IExvY2F0aW9uPC9iPjxicj48YnI+dG90YWwgYWNjaWRlbnRzOiAiLCBkZWFkbHkkbiwgIjxicj52aWN0aW1zOiAiLCBkZWFkbHkkdml0aW1hcywgIjxicj5kZWF0aHM6ICIsIGRlYWRseSR2aXRpbWFzX21vcnRlKQoKIyBtb3N0IHJ1biBvdmVyCnJ1bl9vdmVyIDwtIGRhdGEyMDE1W2RhdGEyMDE1JENPRF9BQ0lEPT00LF0gJT4lCiAgZ3JvdXBfYnkoV0tUKSAlPiUKICBzdW1tYXJpemUobj1uKCksIHZpdGltYXM9c3VtKFZJVElNQVNfTk9STSksIHZpdGltYXNfbW9ydGU9c3VtKFZJVElNQVNfTU9SVEUpKQoKcnVuX292ZXIkbG5nIDwtIGFzLm51bWVyaWMoc3RyX21hdGNoKHJ1bl9vdmVyJFdLVCwgIi4qXFwoKC4qKVxccyguKilcXCkiKVssMl0pCnJ1bl9vdmVyJGxhdCA8LSBhcy5udW1lcmljKHN0cl9tYXRjaChydW5fb3ZlciRXS1QsICIuKlxcKCguKilcXHMoLiopXFwpIilbLDNdKQoKcnVuX292ZXIgPC0gYXJyYW5nZShydW5fb3ZlciwgZGVzYyhuKSkKcnVuX292ZXIgPC0gaGVhZChydW5fb3ZlciwgNSkKcnVuX292ZXIkcG9wdXAgPC0gcGFzdGUoIjxiPlRvcCA1IGluIHJ1biBvdmVyPC9iPjxicj48YnI+dG90YWwgYWNjaWRlbnRzOiAiLCBydW5fb3ZlciRuLCAiPGJyPnZpY3RpbXM6ICIsIHJ1bl9vdmVyJHZpdGltYXMsICI8YnI+ZGVhdGhzOiAiLCBydW5fb3ZlciR2aXRpbWFzX21vcnRlKQoKIyBjcnV6YSBkYWRvcyBkb3MgbG9ncmFkb3Vyb3MKbG9ncmFkb3Vyb3MgPC0gcmVhZC5jc3YoIi4vZGFkb3MvbG9ncmFkb3Vyb3MuY3N2IikKIyBsZXZlbHMobG9ncmFkb3Vyb3MkY2xhc3NpZmljYWNhbykKbG9ncmFkb3Vyb3MgPC0gbG9ncmFkb3Vyb3MgJT4lIAogIGZpbHRlcihjbGFzc2lmaWNhY2FvID09ICJUcmFuc2l0byBSw6FwaWRvIiwgY29kbG9nNSAhPSAiTlVMTCIpICU+JQogIGdyb3VwX2J5KGNvZGxvZzUpICU+JQogIHN1bW1hcml6ZShuPW4oKSkKICAKcnVuX292ZXJfcmFwaWRvIDwtIGRhdGEyMDE1ICU+JQogIGZpbHRlcihDT0RfQUNJRD09NCwgQ0FETE9HQSAlaW4lIGxvZ3JhZG91cm9zJGNvZGxvZzUpCgojIGZhY3RwYWwgPC0gY29sb3JGYWN0b3IodG9wby5jb2xvcnMoMTcpLCBkYXRhMjAxNSRUSVBPX0FDSURFLCBhbHBoYSA9IEZBTFNFLCBvcmRlcmVkID0gVFJVRSkKCmRhdGEyMDE1ICU+JSBsZWFmbGV0KHdpZHRoPTgwMCwgaGVpZ2h0PTUwMCwgcGFkZGluZz01KSAlPiUgYWRkVGlsZXMoKSAlPiUgCiAgYWRkQ2lyY2xlTWFya2VycyhkYXRhID0gZGF0YTIwMTUsIHBvcHVwPX5wb3B1cCwgY2x1c3Rlck9wdGlvbnMgPSBtYXJrZXJDbHVzdGVyT3B0aW9ucygpLCBncm91cD0iYWxsIGFjY2lkZW50cyIsIGNvbG9yPX5jb2xvciwgcmFkaXVzID0gflZJVElNQVNfTk9STSAqIDQsIHdlaWdodCA9IDMsICBmaWxsT3BhY2l0eSA9IH5WSVRJTUFTX01PUlRFICsgMC4yICkgJT4lCiAgYWRkQ2lyY2xlTWFya2VycyhkYXRhID0gcnVuX292ZXJfcmFwaWRvLCBwb3B1cD1+cG9wdXAsIGdyb3VwPSJhdHJvcGVsYW1lbnRvcyBuYXMgdmlhcyBleHByZXNzYXMiLCBjb2xvcj1+Y29sb3IsIHJhZGl1cyA9IDgsIHdlaWdodCA9IDMsICBmaWxsT3BhY2l0eSA9IH5WSVRJTUFTX01PUlRFICsgMC4yICkgJT4lCiAgYWRkQ2lyY2xlTWFya2VycyhkYXRhID0gZGF0YTIwMTVbZGF0YTIwMTUkQ09EX0FDSUQ9PTQsXSwgcG9wdXA9fnBvcHVwLCBjbHVzdGVyT3B0aW9ucyA9IG1hcmtlckNsdXN0ZXJPcHRpb25zKCksIGdyb3VwPSJzb21lbnRlIGF0cm9wZWxhbWVudG9zIiwgY29sb3I9fmNvbG9yLCByYWRpdXMgPSB+VklUSU1BU19OT1JNICogNCwgd2VpZ2h0ID0gMywgZmlsbE9wYWNpdHkgPSB+VklUSU1BU19NT1JURSArIDAuMiApICU+JQogIGFkZE1hcmtlcnMoZGF0YT10b3AxMCwgZ3JvdXA9IndvcnN0IGxvY2F0aW9uIiwgcG9wdXA9fnBvcHVwKSU+JQogIGFkZE1hcmtlcnMoZGF0YT1kZWFkbHksIGdyb3VwPSJkZWFkbHkiLCBwb3B1cD1+cG9wdXApJT4lCiAgYWRkTWFya2VycyhkYXRhPXJ1bl9vdmVyLCBncm91cD0ic29tZW50ZSBhdHJvcGVsYW1lbnRvcyIsIHBvcHVwPX5wb3B1cCklPiUKICBhZGRMYXllcnNDb250cm9sKAogICAgIGJhc2VHcm91cHMgPSBjKCJhbGwgYWNjaWRlbnRzIiwgInNvbWVudGUgYXRyb3BlbGFtZW50b3MiLCAiYXRyb3BlbGFtZW50b3MgbmFzIHZpYXMgZXhwcmVzc2FzIiksCiAgICAgI292ZXJsYXlHcm91cHMgPSBjKCJhY2NpZGVudCIsICJydW4gb3ZlciIsICJ0b3AxMCIsICJkZWFkbHkiKSwKICAgICBvdmVybGF5R3JvdXBzID0gYygid29yc3QgbG9jYXRpb24iLCAiZGVhZGx5IiksCiAgICAgb3B0aW9ucyA9IGxheWVyc0NvbnRyb2xPcHRpb25zKGNvbGxhcHNlZCA9IEZBTFNFKSwKICAgICBwb3NpdGlvbj0iYm90dG9tbGVmdCIKICApCgojIGFkZFJlY3RhbmdsZXMoZGF0YT1sb2NhdGlvbnMsIGxhdDE9fmxhdDEsIGxuZzE9fmxuZzEsIGxhdDI9fmxhdDIsIGxuZzI9fmxuZzIsIGdyb3VwPSJ0b3AxMCIsIHBvcHVwPX5wb3B1cCwgY29sb3I9Im9yYW5nZSIpJT4lCgojYWRkQ2lyY2xlTWFya2Vycyhwb3B1cCA9IH5USVBPX0FDSURFX0RFU0NSLCBjbHVzdGVyT3B0aW9ucyA9IG1hcmtlckNsdXN0ZXJPcHRpb25zKCksIGNvbG9yID0gfmZhY3RwYWwoVElQT19BQ0lERSksIGdyb3VwID0gfkNPRF9BQ0lEKSAlPiUKI2FkZExheWVyc0NvbnRyb2woCiAgIyAgICBvdmVybGF5R3JvdXBzID0gYygyLCA0KSwKICAjICAgIG9wdGlvbnMgPSBsYXllcnNDb250cm9sT3B0aW9ucyhjb2xsYXBzZWQgPSBGQUxTRSkKICAjICkKCiMgYWRkQ2lyY2xlTWFya2Vycyhwb3B1cCA9IH5USVBPX0FDSURFX0RFU0NSLCBjbHVzdGVyT3B0aW9ucyA9IG1hcmtlckNsdXN0ZXJPcHRpb25zKCksIGNvbG9yID0gfmZhY3RwYWwoVElQT19BQ0lERSkpIAoKIyAlPiUgYWRkTGVnZW5kKHBhbCA9IGZhY3RwYWwsIHZhbHVlcyA9IH5USVBPX0FDSURFX0RFU0NSLCBvcGFjaXR5ID0gMSwgdGl0bGUgPSAiVHJhZmZpYyBJbmNpZGVudHMgLSAyMDE1IikKCgpgYGAKCgotLS0tCgoKIyMgQXBwZW5kaXggSSAtIFNvdXJjZSBDb2RlCgpNYWRlIHdpdGggW1JdKGh0dHBzOi8vd3d3LnJzdHVkaW8uY29tLykgYW5kIFtMZWFmbGV0XShodHRwczovL3JzdHVkaW8uZ2l0aHViLmlvL2xlYWZsZXQvKSwgc291cmNlIGNvZGU6CgpgYGB7ciwgZXZhbD1GQUxTRX0KIyBsb2FkIGxpYnJhcmllcwojIGluc3RhbGwucGFja2FnZXMoImxlYWZsZXQiKQojIGluc3RhbGwucGFja2FnZXMoImRwbHlyIikKc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKGxpYnJhcnkobGVhZmxldCkpCnN1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyhsaWJyYXJ5KHN0cmluZ3IpKQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMobGlicmFyeShkcGx5cikpCgojbG9hZCBhbmQgY2xlYW4KZGF0YTIwMTUgPC0gcmVhZC5jc3YoIi4vZGFkb3MvMjAxNS9vY29ycmVuY2lhcy10cmFuc2l0by1wbXNwLTIwMTUuY3N2IikKZGF0YTIwMTUkbG5nIDwtIGFzLm51bWVyaWMoc3RyX21hdGNoKGRhdGEyMDE1JFdLVCwgIi4qXFwoKC4qKVxccyguKilcXCkiKVssMl0pCmRhdGEyMDE1JGxhdCA8LSBhcy5udW1lcmljKHN0cl9tYXRjaChkYXRhMjAxNSRXS1QsICIuKlxcKCguKilcXHMoLiopXFwpIilbLDNdKQpkYXRhMjAxNSA8LSBkYXRhMjAxNVtjb21wbGV0ZS5jYXNlcyhkYXRhMjAxNVssYygibGF0IiwibG5nIildKSxdCgojIGFkZCBsZWdlbmRhIGNvbSBvIFRJUE9fQUNJREUKZGF0YTIwMTUkVElQT19BQ0lERV9ERVNDUltkYXRhMjAxNSRUSVBPX0FDSURFPT0iQ08iXSA8LSAiQ29saXPDo28iCmRhdGEyMDE1JFRJUE9fQUNJREVfREVTQ1JbZGF0YTIwMTUkVElQT19BQ0lERT09IkNGIl0gPC0gIkNvbGlzw6NvIGZyb250YWwiCmRhdGEyMDE1JFRJUE9fQUNJREVfREVTQ1JbZGF0YTIwMTUkVElQT19BQ0lERT09IkNUIl0gPC0gIkNvbGlzw6NvIHRyYXNlaXJhIgpkYXRhMjAxNSRUSVBPX0FDSURFX0RFU0NSW2RhdGEyMDE1JFRJUE9fQUNJREU9PSJDTCJdIDwtICJDb2xpc8OjbyBsYXRlcmFsIgpkYXRhMjAxNSRUSVBPX0FDSURFX0RFU0NSW2RhdGEyMDE1JFRJUE9fQUNJREU9PSJDViJdIDwtICJDb2xpc8OjbyBUcmFuc3ZlcnNhIgpkYXRhMjAxNSRUSVBPX0FDSURFX0RFU0NSW2RhdGEyMDE1JFRJUE9fQUNJREU9PSJDUCJdIDwtICJDYXBvdGFtZW50byIKZGF0YTIwMTUkVElQT19BQ0lERV9ERVNDUltkYXRhMjAxNSRUSVBPX0FDSURFPT0iVEIiXSA8LSAiVG9tYmFtZW50byIKZGF0YTIwMTUkVElQT19BQ0lERV9ERVNDUltkYXRhMjAxNSRUSVBPX0FDSURFPT0iQVQiXSA8LSAiQXRyb3BlbGFtZW50byIKZGF0YTIwMTUkVElQT19BQ0lERV9ERVNDUltkYXRhMjAxNSRUSVBPX0FDSURFPT0iQUEiXSA8LSAiQXRyb3BlbGFtZW50byBhbmltYWwiCmRhdGEyMDE1JFRJUE9fQUNJREVfREVTQ1JbZGF0YTIwMTUkVElQT19BQ0lERT09IkNIIl0gPC0gIkNob3F1ZSIKZGF0YTIwMTUkVElQT19BQ0lERV9ERVNDUltkYXRhMjAxNSRUSVBPX0FDSURFPT0iUU0iXSA8LSAiUXVlZGEgbW90by9iaWNpY2xldGEiCmRhdGEyMDE1JFRJUE9fQUNJREVfREVTQ1JbZGF0YTIwMTUkVElQT19BQ0lERT09IlFWIl0gPC0gIlF1ZWRhIHZlw61jdWxvIgpkYXRhMjAxNSRUSVBPX0FDSURFX0RFU0NSW2RhdGEyMDE1JFRJUE9fQUNJREU9PSJRRCJdIDwtICJRdWVkYSBvY3VwYW50ZSBkZW50cm8iCmRhdGEyMDE1JFRJUE9fQUNJREVfREVTQ1JbZGF0YTIwMTUkVElQT19BQ0lERT09IlFGIl0gPC0gIlF1ZWRhIG9jdXBhbnRlIGZvcmEiCmRhdGEyMDE1JFRJUE9fQUNJREVfREVTQ1JbZGF0YTIwMTUkVElQT19BQ0lERT09Ik9VIl0gPC0gIk91dHJvcyIKZGF0YTIwMTUkVElQT19BQ0lERV9ERVNDUltkYXRhMjAxNSRUSVBPX0FDSURFPT0iU0kiXSA8LSAiU2VtIGluZm9ybWHDp8OjbyIKCiMgbm9ybWFsaXphIG51bWVybyBkZSB2aXRpbWFzCmRhdGEyMDE1JFZJVElNQVNfTk9STVtkYXRhMjAxNSRWSVRJTUFTIDwgMTAwXSA8LSBkYXRhMjAxNVtkYXRhMjAxNSRWSVRJTUFTIDwgMTAwLDE3XQpkYXRhMjAxNSRWSVRJTUFTX05PUk1bZGF0YTIwMTUkVklUSU1BUyA+PSAxMDBdIDwtIGRhdGEyMDE1W2RhdGEyMDE1JFZJVElNQVMgPj0gMTAwLDE3XSAlLyUgMTAwCmRhdGEyMDE1JFZJVElNQVNfTU9SVEUgPC0gMApkYXRhMjAxNSRWSVRJTUFTX01PUlRFW2RhdGEyMDE1JFZJVElNQVMgPj0gMTAwXSA8LSBkYXRhMjAxNVtkYXRhMjAxNSRWSVRJTUFTID49IDEwMCwxN10gJSUgMTAwCgojIHBvcHVwCmRhdGEyMDE1JHBvcHVwIDwtIHBhc3RlKGRhdGEyMDE1JFRJUE9fQUNJREVfREVTQ1IsICI8YnI+PGJyPnZpdGltYXMgZmVyaWRhczoiLCBkYXRhMjAxNSRWSVRJTUFTX05PUk0sICI8YnI+dml0aW1hcyBmYXRhaXM6IiwgZGF0YTIwMTUkVklUSU1BU19NT1JURSwgIjxicj5jb2QuIGxvY2FsaXphw6fDo286ICIsIGRhdGEyMDE1JENBRExPR0EpOwoKIyBjb2xvcgpkYXRhMjAxNSRjb2xvcltkYXRhMjAxNSRDT0RfQUNJRD09Ml0gPC0gImJsdWUiCmRhdGEyMDE1JGNvbG9yW2RhdGEyMDE1JENPRF9BQ0lEPT00XSA8LSAicmVkIiAKCiMgdG9wIDEwIGxvY2F0aW9ucwpsb2NhdGlvbnMgPC0gZGF0YTIwMTUgJT4lCiAgZ3JvdXBfYnkoV0tUKSAlPiUKICBzdW1tYXJpemUobj1uKCksIHZpdGltYXM9c3VtKFZJVElNQVNfTk9STSksIHZpdGltYXNfbW9ydGU9c3VtKFZJVElNQVNfTU9SVEUpKQoKbG9jYXRpb25zJGxuZyA8LSBhcy5udW1lcmljKHN0cl9tYXRjaChsb2NhdGlvbnMkV0tULCAiLipcXCgoLiopXFxzKC4qKVxcKSIpWywyXSkKbG9jYXRpb25zJGxhdCA8LSBhcy5udW1lcmljKHN0cl9tYXRjaChsb2NhdGlvbnMkV0tULCAiLipcXCgoLiopXFxzKC4qKVxcKSIpWywzXSkKCmxvY2F0aW9ucyA8LSBhcnJhbmdlKGxvY2F0aW9ucywgZGVzYyhuKSkKCnRvcDEwIDwtIGhlYWQobG9jYXRpb25zLCAxMCkKCnRvcDEwJHBvcHVwIDwtIHBhc3RlKCI8Yj5UT1AgMTAgaW4gbnVtYmVyIG9mIGFjY2lkZW50czwvYj48YnI+PGJyPnRvdGFsIGFjY2lkZW50czogIiwgdG9wMTAkbiwgIjxicj52aWN0aW1zOiAiLCB0b3AxMCR2aXRpbWFzLCAiPGJyPmRlYXRoczogIiwgdG9wMTAkdml0aW1hc19tb3J0ZSkKCmxvY2F0aW9ucyA8LSBhcnJhbmdlKGxvY2F0aW9ucywgZGVzYyh2aXRpbWFzX21vcnRlKSkKZGVhZGx5IDwtIGhlYWQobG9jYXRpb25zLCAxMCkKZGVhZGx5JHBvcHVwIDwtIHBhc3RlKCI8Yj5EZWFkbHkgTG9jYXRpb248L2I+PGJyPjxicj50b3RhbCBhY2NpZGVudHM6ICIsIGRlYWRseSRuLCAiPGJyPnZpY3RpbXM6ICIsIGRlYWRseSR2aXRpbWFzLCAiPGJyPmRlYXRoczogIiwgZGVhZGx5JHZpdGltYXNfbW9ydGUpCgojIG1vc3QgcnVuIG92ZXIKcnVuX292ZXIgPC0gZGF0YTIwMTVbZGF0YTIwMTUkQ09EX0FDSUQ9PTQsXSAlPiUKICBncm91cF9ieShXS1QpICU+JQogIHN1bW1hcml6ZShuPW4oKSwgdml0aW1hcz1zdW0oVklUSU1BU19OT1JNKSwgdml0aW1hc19tb3J0ZT1zdW0oVklUSU1BU19NT1JURSkpCgpydW5fb3ZlciRsbmcgPC0gYXMubnVtZXJpYyhzdHJfbWF0Y2gocnVuX292ZXIkV0tULCAiLipcXCgoLiopXFxzKC4qKVxcKSIpWywyXSkKcnVuX292ZXIkbGF0IDwtIGFzLm51bWVyaWMoc3RyX21hdGNoKHJ1bl9vdmVyJFdLVCwgIi4qXFwoKC4qKVxccyguKilcXCkiKVssM10pCgpydW5fb3ZlciA8LSBhcnJhbmdlKHJ1bl9vdmVyLCBkZXNjKG4pKQpydW5fb3ZlciA8LSBoZWFkKHJ1bl9vdmVyLCA1KQpydW5fb3ZlciRwb3B1cCA8LSBwYXN0ZSgiPGI+VG9wIDUgaW4gcnVuIG92ZXI8L2I+PGJyPjxicj50b3RhbCBhY2NpZGVudHM6ICIsIHJ1bl9vdmVyJG4sICI8YnI+dmljdGltczogIiwgcnVuX292ZXIkdml0aW1hcywgIjxicj5kZWF0aHM6ICIsIHJ1bl9vdmVyJHZpdGltYXNfbW9ydGUpCgojIGNydXphIGRhZG9zIGRvcyBsb2dyYWRvdXJvcwpsb2dyYWRvdXJvcyA8LSByZWFkLmNzdigiLi9kYWRvcy9sb2dyYWRvdXJvcy5jc3YiKQojIGxldmVscyhsb2dyYWRvdXJvcyRjbGFzc2lmaWNhY2FvKQpsb2dyYWRvdXJvcyA8LSBsb2dyYWRvdXJvcyAlPiUgCiAgZmlsdGVyKGNsYXNzaWZpY2FjYW8gPT0gIlRyYW5zaXRvIFLDoXBpZG8iLCBjb2Rsb2c1ICE9ICJOVUxMIikgJT4lCiAgZ3JvdXBfYnkoY29kbG9nNSkgJT4lCiAgc3VtbWFyaXplKG49bigpKQogIApydW5fb3Zlcl9yYXBpZG8gPC0gZGF0YTIwMTUgJT4lCiAgZmlsdGVyKENPRF9BQ0lEPT00LCBDQURMT0dBICVpbiUgbG9ncmFkb3Vyb3MkY29kbG9nNSkKCiMgZmFjdHBhbCA8LSBjb2xvckZhY3Rvcih0b3BvLmNvbG9ycygxNyksIGRhdGEyMDE1JFRJUE9fQUNJREUsIGFscGhhID0gRkFMU0UsIG9yZGVyZWQgPSBUUlVFKQoKZGF0YTIwMTUgJT4lIGxlYWZsZXQod2lkdGg9ODAwLCBoZWlnaHQ9NTAwLCBwYWRkaW5nPTUpICU+JSBhZGRUaWxlcygpICU+JSAKICBhZGRDaXJjbGVNYXJrZXJzKGRhdGEgPSBkYXRhMjAxNSwgcG9wdXA9fnBvcHVwLCBjbHVzdGVyT3B0aW9ucyA9IG1hcmtlckNsdXN0ZXJPcHRpb25zKCksIGdyb3VwPSJhbGwgYWNjaWRlbnRzIiwgY29sb3I9fmNvbG9yLCByYWRpdXMgPSB+VklUSU1BU19OT1JNICogNCwgd2VpZ2h0ID0gMywgIGZpbGxPcGFjaXR5ID0gflZJVElNQVNfTU9SVEUgKyAwLjIgKSAlPiUKICBhZGRDaXJjbGVNYXJrZXJzKGRhdGEgPSBydW5fb3Zlcl9yYXBpZG8sIHBvcHVwPX5wb3B1cCwgZ3JvdXA9ImF0cm9wZWxhbWVudG9zIG5hcyB2aWFzIGV4cHJlc3NhcyIsIGNvbG9yPX5jb2xvciwgcmFkaXVzID0gOCwgd2VpZ2h0ID0gMywgIGZpbGxPcGFjaXR5ID0gflZJVElNQVNfTU9SVEUgKyAwLjIgKSAlPiUKICBhZGRDaXJjbGVNYXJrZXJzKGRhdGEgPSBkYXRhMjAxNVtkYXRhMjAxNSRDT0RfQUNJRD09NCxdLCBwb3B1cD1+cG9wdXAsIGNsdXN0ZXJPcHRpb25zID0gbWFya2VyQ2x1c3Rlck9wdGlvbnMoKSwgZ3JvdXA9InNvbWVudGUgYXRyb3BlbGFtZW50b3MiLCBjb2xvcj1+Y29sb3IsIHJhZGl1cyA9IH5WSVRJTUFTX05PUk0gKiA0LCB3ZWlnaHQgPSAzLCBmaWxsT3BhY2l0eSA9IH5WSVRJTUFTX01PUlRFICsgMC4yICkgJT4lCiAgYWRkTWFya2VycyhkYXRhPXRvcDEwLCBncm91cD0id29yc3QgbG9jYXRpb24iLCBwb3B1cD1+cG9wdXApJT4lCiAgYWRkTWFya2VycyhkYXRhPWRlYWRseSwgZ3JvdXA9ImRlYWRseSIsIHBvcHVwPX5wb3B1cCklPiUKICBhZGRNYXJrZXJzKGRhdGE9cnVuX292ZXIsIGdyb3VwPSJzb21lbnRlIGF0cm9wZWxhbWVudG9zIiwgcG9wdXA9fnBvcHVwKSU+JQogIGFkZExheWVyc0NvbnRyb2woCiAgICAgYmFzZUdyb3VwcyA9IGMoImFsbCBhY2NpZGVudHMiLCAic29tZW50ZSBhdHJvcGVsYW1lbnRvcyIsICJhdHJvcGVsYW1lbnRvcyBuYXMgdmlhcyBleHByZXNzYXMiKSwKICAgICBvdmVybGF5R3JvdXBzID0gYygid29yc3QgbG9jYXRpb24iLCAiZGVhZGx5IiksCiAgICAgb3B0aW9ucyA9IGxheWVyc0NvbnRyb2xPcHRpb25zKGNvbGxhcHNlZCA9IEZBTFNFKSwKICAgICBwb3NpdGlvbj0iYm90dG9tbGVmdCIKICApCmBgYA==